package com.easymin.weixin.controller.h5.v4;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.easymin.weixin.controller.v4.ResultTransport;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.easymin.weixin.common.WxUtils;
import com.easymin.weixin.common.api.PassengerApi;
import com.easymin.weixin.common.api.SalesApi;
import com.easymin.weixin.common.api.ZhuanXianApi;
import com.easymin.weixin.entity.WxAccount;
import com.easymin.weixin.entity.WxApplication;
import com.easymin.weixin.manager.WxAccountManager;
import com.easymin.weixin.manager.WxApplicationManager;
import com.google.common.base.Preconditions;

/**
 * Created by shine on 15/12/29.
 */
@RestController
@RequestMapping("h5/v4/zhuanxian")
public class ZhuanxianV4Controller {

  private static final String WX_ACCESS_TOKEN =
      "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";

  private static final String WX_JSAPI_TICKET =
      "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={access_token}&type=jsapi";


  @Autowired
  private SalesApi salesApi;

  @Autowired
  private WxApplicationManager wxApplicationManager;

  @Autowired
  private WxAccountManager wxAccountManager;

  @Autowired
  private ZhuanXianApi zhuanXianApi;

  @Autowired
  private RestTemplate restTemplate;

  @Autowired
  private PassengerApi passengerApi;


  /**
   * 查询所有路线.
   * @param appKey 系统key
   * @param lat 纬度
   * @param lng 经度
   * @return JSONArray
   */
  @RequestMapping("findLineAll")
  public JSONArray findLineAll(@RequestParam("appkey") String appKey,
      @RequestParam("lat") Double lat, @RequestParam("lng") Double lng) {


    JSONArray jsonArray = zhuanXianApi.findLineAll(lat, lng, appKey);

    return jsonArray;
  }

  /**
   * 查询路线.
   * @param appKey 系统key
   * @param startCity 开始城市
   * @param endCity 结束城市
   * @return JSONArray
   */
  @RequestMapping("findLineAllBySE")
  public JSONArray findLineAll(@RequestParam("appkey") String appKey, @RequestParam(
      required = false, value = "startCity") String startCity, @RequestParam(required = false,
      value = "endCity") String endCity) {


    JSONArray jsonArray = zhuanXianApi.findLineAllByCity(startCity, endCity, appKey);

    return jsonArray;
  }

  /**
   * 预算费用.
   * @param appKey 系统key
   * @param areaId 收费id
   * @param startLat 开始纬度
   * @param startLng 开始经度
   * @param endLat 结束纬度
   * @param endLng 结束经度
   * @return JSONObject
   */
  @RequestMapping("budgetedExpense")
  public JSONObject budgetedExpense(
	  @RequestParam("appkey") String appKey,
      @RequestParam("areaId") Long areaId, 
      @RequestParam("startLat") Double startLat,
      @RequestParam("startLng") Double startLng,
      @RequestParam(required = false, value = "endLat") Double endLat, 
      @RequestParam(required = false, value = "endLng") Double endLng) {

    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");


    JSONObject json =
        zhuanXianApi.budgetedExpense(wxApplication.getAddress(), areaId, startLat, startLng,
            endLat, endLng);

    return json;
  }

  /**
   * 根据路线id查询.
   * @param appKey 系统key
   * @param lineId 路线id
   * @return JSONObject
   */
  @RequestMapping("findBylineId")
  public JSONObject findBylineId(@RequestParam("appkey") String appKey,
      @RequestParam("lineId") Long lineId) {

    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return zhuanXianApi.findBylineId(wxApplication.getAddress(), lineId);
  }

  /**
   * 下单V4.
   * @param appKey 系统key
   * @param orderType 订单类型
   * @param passengerId 客户id  false
   * @param passengerPhone 客户手机号
   * @param lineId 路线id
   * @param startAddress 开始地址
   * @param startLat 开始纬度
   * @param startLng 开始经度
   * @param endAddress 结束地址 false
   * @param endLat 结束纬度 false
   * @param ack 区分公司 false
   * @param lat 纬度 false
   * @param lng 经度 false
   * @param endLng 结束经度 false
   * @param startTime 开始时间
   * @param budgetPay 预算价格 false
   * @param memo 备注 false
   * @param couponId 优惠券id false
   * @param peopleNumber 人数 false
   * @param takeDeliveryName 收货人名称 false
   * @param takeDeliveryPhone 收货人电话 false
   * @param openId 微信id false
   * @return JSONObject
   */
  @RequestMapping(value = "makeAnZXAppointmentV4", method = RequestMethod.POST)
  public JSONObject makeAnZhuanxianAppointmentV4(
      @RequestParam("appkey") String appKey,
      @RequestParam("orderType") String orderType,
      @RequestParam(required = false, value = "passengerId") Long passengerId,
      @RequestParam("passengerPhone") String passengerPhone,
      @RequestParam("lineId") Long lineId,
      @RequestParam("startAddress") String startAddress, 
      @RequestParam("startLat") Double startLat,
      @RequestParam("startLng") Double startLng,
      @RequestParam(required = false, value = "endAddress") String endAddress,
      @RequestParam(required = false, value = "endLat") Double endLat, 
      @RequestParam(required = false, value = "ack") String ack,
      @RequestParam(required = false, value = "lat") Double lat, 
      @RequestParam(required = false, value = "lng") Double lng,
      @RequestParam(required = false, value = "endLng") Double endLng,
      @RequestParam("startTime") Date startTime, 
      @RequestParam(required = false, value = "budgetPay") Double budgetPay,
      @RequestParam(required = false, value = "memo") String memo, 
      @RequestParam(required = false, value = "couponId") Long couponId,
      @RequestParam(required = false, value = "peopleNumber") Long peopleNumber,
      @RequestParam(required = false, value = "takeDeliveryName") String takeDeliveryName, 
      @RequestParam(required = false, value = "takeDeliveryPhone") String takeDeliveryPhone,
      @RequestParam(required = false, value = "openId") String openId) throws ParseException {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");
    long serverTimeLong = startTime.getTime();
    return zhuanXianApi.makeAnZhuanxianAppointmentV4(wxApplication.getAddress(), appKey, orderType,
        passengerId, passengerPhone, lineId, startAddress, startLat, startLng, endAddress, endLat,
        endLng, serverTimeLong, budgetPay, couponId, peopleNumber, memo, takeDeliveryName,
        takeDeliveryPhone, ack, lat, lng, openId);
  }

  /**
   *  取消订单.
   * @param appKey 系统key
   * @param orderId 订单id
   * @param reson 原因
   * @return JSONObject
   */
  @RequestMapping(value = "cancelOrder", method = RequestMethod.POST)
  public JSONObject cancelOrder(
      @RequestParam("appkey") String appKey,
      @RequestParam("orderId") Long orderId, 
      @RequestParam("reson") String reson) {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return zhuanXianApi.cancelZhuanxianOrder(orderId, reson, appKey);
  }

  /**
   * 查询未完成订单信息.
   * @param appKey 系统key
   * @param passengerId 客户id
   * @return JSONArray
   */
  @RequestMapping(value = "findRunning")
  public JSONArray findRunning(
      @RequestParam("appkey") String appKey,
      @RequestParam("passengerId") Long passengerId) throws Exception {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return zhuanXianApi.findRunning(passengerId, appKey);
  }

  /**
   * 查询订单信息.
   * @param appKey 系统key
   * @param orderId 订单id
   * @return JSONObject
   */
  @RequestMapping(value = "findZXOrder")
  public JSONObject findZhuanxianOrder(
      @RequestParam("appkey") String appKey,
      @RequestParam("orderId") Long orderId) throws Exception {

    return zhuanXianApi.findZhuanxianOrder(appKey, orderId);
  }

  /**
   * 专线查询优惠券.
   * @param appKey 系统key
   * @param passengerId 客户id
   * @return JSONArray
   */
  @RequestMapping(value = "findZXCouponV4", method = RequestMethod.GET)
  public JSONArray findZhuanxianCouponV4(
      @RequestParam("appkey") String appKey,
      @RequestParam("passengerId") Long passengerId,@RequestParam(required = false, value = "lineId") Long lineId) {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");
    Preconditions.checkArgument(null != passengerId, "passengerId错误");
    JSONArray jsonArray = new JSONArray();
    if(null != lineId){
      JSONObject jsonObject = zhuanXianApi.findReturnLine(lineId,appKey);
      JSONObject jj = jsonObject.getJSONObject("data");
      StringBuilder linesBuild = new StringBuilder();
      linesBuild.append(lineId);
      if(null != jj){
        linesBuild.append(",");
        linesBuild.append(jj.get("id"));
      }
      jsonArray = salesApi.findCouponV4(passengerId, "zhuanxian", appKey, linesBuild.toString());
    }

    return jsonArray;
  }

  /**
   * 获取相向的两条线路
   * @param lineId
   * @param appKey
   * @return
   */
  public String getRelativeLine(Long lineId, String appKey){
    JSONObject jsonObject = zhuanXianApi.findReturnLine(lineId,appKey);
    JSONObject jj = jsonObject.getJSONObject("data");

    StringBuilder linesBuild = new StringBuilder();
    linesBuild.append(lineId);
    if(null != jj){
      linesBuild.append(",");
      linesBuild.append(jj.get("id"));
    }
    String result = linesBuild.toString();
    return result;
  }

  /**
   * 获取可领取优惠券
   * @param appKey
   * @param lineId
   * @param phone
   * @param passengerId
   * @param activityEvent
   * @return
   */
  @RequestMapping(value = "findAvailableCoupon", method = RequestMethod.GET)
  public JSONObject findAvailableCoupon(@RequestParam(required = false, value = "appKey") String appKey,
                                       @RequestParam(required = false, value = "lineId") Long lineId,
                                       @RequestParam(required = false, value = "phone") String phone,
                                       @RequestParam(required = false, value = "passengerId") Long passengerId,
                                       @RequestParam(required = false, value = "activityEvent") String activityEvent){
    if (StringUtils.isBlank(appKey) || null == lineId || StringUtils.isBlank(phone) || null == passengerId || StringUtils.isBlank(activityEvent)) {
      JSONObject jsonObject = new JSONObject();

      return jsonObject;
    }
    Preconditions.checkArgument(null != appKey, "appKey错误");
    Preconditions.checkArgument(null != lineId, "lineId错误");
    Preconditions.checkArgument(StringUtils.isNoneBlank(phone), "phone错误");
    Preconditions.checkArgument(null != passengerId, "passengerId错误");
    Preconditions.checkArgument(StringUtils.isNoneBlank(activityEvent), "activityEvent错误");
    String linesId = getRelativeLine(lineId,appKey);
    String result = salesApi.findOneCoupon(appKey,linesId,phone,passengerId,activityEvent);
    JSONObject json = JSON.parseObject(result);
    return json;
  }

  /**
   * 评价订单.
   * @param appKey 系统key
   * @param score 评价等级
   * @param orderId 订单id
   * @param content 内容
   * @return JSONObject
   */
  @RequestMapping(value = "review")
  public JSONObject review(
      @RequestParam("appkey") String appKey,
      @RequestParam("score") Double score,
      @RequestParam("orderId") Long orderId, 
      @RequestParam(required = false, value = "content") String content) throws Exception {

    return zhuanXianApi.review(orderId, score, content, appKey);
  }

  /**
   *  微信支付.
   * @param appKey 系统key
   * @param orderId 订单id
   * @param openid 微信id
   * @param appid 微信应用id
   * @param request 判断是否来自微信
   * @return JSONObject
   */
  @RequestMapping(value = "doPayForWx", method = RequestMethod.POST)
  public JSONObject doPayForWx(
      @RequestParam("appkey") String appKey,
      @RequestParam("orderId") Long orderId,
      @RequestParam("openid") String openid,
      @RequestParam("appid") String appid, 
      HttpServletRequest request) {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    WxAccount wxAccount = wxAccountManager.findBy(appid, wxApplication.getId());
    Preconditions.checkArgument(null != wxAccount, "appid错误");

    // 判断是否来自微信
    StringBuilder sb = new StringBuilder();
    sb.append(request.getScheme());
    sb.append("://");
    sb.append(request.getServerName());
    int port = request.getServerPort();
    if (port != 80) {
      sb.append(":").append(port);
    }
    sb.append(request.getRequestURI());
    String queryString = request.getQueryString();
    if (StringUtils.isNotBlank(queryString)) {
      sb.append("?");
      sb.append(queryString);
    }

    JSONObject jsonObject = new JSONObject();

    JSONObject jo = zhuanXianApi.getZxWxPrepayId(wxApplication.getAddress(), orderId, openid);
    jsonObject.put("package", jo.getString("package"));
    jsonObject.put("timestamp", jo.getString("timeStamp"));
    jsonObject.put("url", sb.toString());
    jsonObject.put("nonceStr", jo.getString("nonceStr"));
    jsonObject.put("paySign", jo.getString("paySign"));

    // 获取微信AccessToken
    String response =
        restTemplate.getForObject(WX_ACCESS_TOKEN, String.class, wxAccount.getWxappId(),
            wxAccount.getAppsecret());
    JSONObject ac = JSON.parseObject(response);

    if (ac.containsKey("access_token")) {
      String accessToken = ac.getString("access_token"); // 获取微信access_token

      // 获取jsapi_ticket
      String resp = restTemplate.getForObject(WX_JSAPI_TICKET, String.class, accessToken);
      JSONObject ticketJson = JSON.parseObject(resp);
      if (ticketJson.containsKey("ticket")) {

        String ticket = ticketJson.getString("ticket");

        jsonObject.put("jsapi_ticket", ticket);

        Map<String, Object> signParams = new HashMap<>();
        signParams.put("jsapi_ticket", ticket);
        signParams.put("timestamp", jo.getString("timestamp"));
        signParams.put("url", sb.toString());
        signParams.put("nonceStr", jo.getString("noncestr"));

        jsonObject.put("signature", WxUtils.buildSha1Sign(signParams));
      }
    }

    return jsonObject;
  }

  /**
   * 进行支付.
   * @param appKey 系统key
   * @param orderId 订单id
   * @param payType 支付类型
   * @return Object
   */
  @RequestMapping(value = "doPay", method = RequestMethod.POST)
  public Object doPay(
      @RequestParam("appkey") String appKey,
      @RequestParam("orderId") Long orderId,
      @RequestParam("payType") String payType) {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return zhuanXianApi.finishTaskZhuanxian(
        wxApplication.getAddress(), orderId, payType, "passenger");

  }

  /**
   * 获取专线订单是否已经被支付.
   * @param appKey 系统key
   * @param orderId 订单id
   * @return Object
   */
  @RequestMapping(value = "hasPayed", method = RequestMethod.GET)
  public Object hasPayed(@RequestParam("appkey") String appKey,
      @RequestParam("orderId") Long orderId) {

    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return zhuanXianApi.checkTaskZhuanxian(wxApplication.getAddress(), orderId);
  }

  /**
   * 获取支付信息.
   * @param appKey 系统key
   * @param orderId 订单id
   * @return Object
   */
  @RequestMapping(value = "prepay", method = RequestMethod.GET)
  public Object prepay(
      @RequestParam("appkey") String appKey, 
      @RequestParam("orderId") Long orderId) {
    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
    Preconditions.checkArgument(null != wxApplication, "appKey错误");

    return zhuanXianApi.clientPayDataZhuanxian(wxApplication.getAddress(), orderId);
  }

}
